﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using Tauren.Business.DLL.Menus;
using Tauren.Business.DLL.Resouces;
using Tauren.Business.Entity.Config;
using Tauren.Business.Entity.Const;
using Tauren.Business.Entity.Enum;
using Tauren.Business.Entity.Global;
using Tauren.Business.Entity.Input;
using Tauren.Business.Entity.Output;
using Tauren.Business.Infrastructure;
using Tauren.Business.Infrastructure.Globals;
using Model = Tauren.Business.Entity.Model;
using OutPut = Tauren.Business.Entity.Output;

namespace Tauren.Business.Service.Menus
{
    public class MenuService : Base.BaseService, IMenuService
    {
        public MenuService(IMenuBusiness business, IConnectionBLLBase connectionBLL, IMenuResourcesBusiness menuResources) : base(business, connectionBLL, menuResources)
        {
            ///获取资源数据
            this.ResourcesInfo = GetResources(GlobalConst.RESOURCES_FLAG_MODULE_MENUS_KEY);
            this.JudePrmission(GlobalConst.RESOURCES_FLAG_MODULE_MENUS_KEY.ToLower());
            this.business = business;
        }

        private IMenuBusiness business { get; set; }

        /// <summary>
        /// 新增菜单数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public IResponseMessage Add(Menus_InPut input)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            Model.Menus model = null;
            ToModel<Model.Menus, Menus_InPut>(input, out model);
            if (model == null)
                return ErrorType.BUSINESS_MENU_NOTFOUND_INPUT_DATA_ERROR.Failure(this.Resources(ErrorType.BUSINESS_MENU_NOTFOUND_INPUT_DATA_ERROR));
            model.Creatdate = DateTime.Now;
            model.Creator = Global.EmpId;
            var dbModel = business.GetByCode(model.Code);
            if (dbModel == null)
            {
                double seq = business.GetSequenceByParentCode(model.ParentCode);
                model.Sequence = seq + 1;
                return business.Add(model).Succeed();
            }
            else return ErrorType.BUSINESS_MENU_REPEAT_ACCOUNT.Failure(this.Resources(ErrorType.BUSINESS_MENU_REPEAT_ACCOUNT));
        }

        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public IResponseMessage Delete(object id)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            List<Model.Menus> ChildMenus = business.GetMenusByParentCode(id);
            if (ChildMenus.Any()) return ErrorType.BUSINESS_MENU_UNREMOVE.Failure(this.Resources(ErrorType.BUSINESS_MENU_UNREMOVE));
            return business.Delete(id).Succeed();
        }

        public IResponseMessage Editor(Menus_InPut input)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            Model.Menus model = null;
            ToModel<Model.Menus, Menus_InPut>(input, out model);
            if (model == null)
                return ErrorType.BUSINESS_MENU_NOTFOUND_INPUT_DATA_ERROR.Failure(this.Resources(ErrorType.BUSINESS_MENU_NOTFOUND_INPUT_DATA_ERROR));
            var dbModel = business.GetByCode(model.Code);
            if (dbModel != null)
            {
                model.Creatdate = dbModel.Creatdate;
                model.Creator = dbModel.Creator;
                return business.Update(model).Succeed();
            }
            else return ErrorType.BUSINESS_MENU_DB_NOT_FOUND.Failure(this.Resources(ErrorType.BUSINESS_MENU_DB_NOT_FOUND));
        }

        /// <summary>
        /// 禁用菜单
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public IResponseMessage Enable(int id)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            Model.Menus menus = business.Get<Model.Menus>(id);
            if (menus == null) return ErrorType.BUSINESS_MENU_DB_NOT_FOUND.Failure(this.Resources(ErrorType.BUSINESS_MENU_DB_NOT_FOUND));
            menus.Status = !menus.Status;
            bool b = business.Update<Model.Menus>(menus);
            return b.Succeed();
        }

        /// <summary>
        /// 获取单个信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public IResponseMessage FirstOrDefault(object id)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            Model.Menus menus = business.Get<Model.Menus>(id);
            OutPut.Menus_OuPut _OutPut = new OutPut.Menus_OuPut();
            ToViewModel<Model.Menus, OutPut.Menus_OuPut>(menus, out _OutPut);
            if (_OutPut != null)
            {
                _OutPut.Dic_Creator = ToSingeUserInfoName(_OutPut.Creator.Value, Global.Language);
            }
            return _OutPut.Succeed();
        }

        /// <summary>
        /// 获取菜单树
        /// </summary>
        /// <returns></returns>
        public IResponseMessage Menus()
        {
            List<Model.Menus> menus = business.GetMenus();
            List<OutPut.MenusInfo_OuPut> _OuPuts = new List<OutPut.MenusInfo_OuPut>();
            menus.Where(o => string.IsNullOrEmpty(o.ParentCode)).ToList().ForEach(o =>
             {
                 if (!_OuPuts.Any(no => no.Code == o.Code))
                     _OuPuts.Add(
                         new OutPut.MenusInfo_OuPut()
                         {
                             Code = o.Code,
                             Icon = o.Icon,
                             Index = string.IsNullOrEmpty(o.Address) ? o.MenuId.ToString() : o.Address,
                             Title = Global.Language == "zh-cn" ? o.CNName : string.IsNullOrEmpty(o.ENName) ? o.CNName : o.ENName,
                             Subs = GenerateChildMenus(o.Code, menus)
                         });
             });
            return _OuPuts.Succeed();
        }

        /// <summary>
        /// 获取菜单列表
        /// </summary>
        /// <returns></returns>
        public IResponseMessage Tables()
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            List<Model.Menus> menus = business.All<Model.Menus>();
            List<OutPut.Menus_OuPut> _OuPuts = new List<OutPut.Menus_OuPut>();
            var empDictionary = this.EmpDictionary;
            int i = 1;
            menus.Where(o => string.IsNullOrEmpty(o.ParentCode)).OrderBy(o => o.Sequence).ToList().ForEach(o =>
              {
                  _OuPuts.Add(
                      new OutPut.Menus_OuPut()
                      {
                          Icon = o.Icon,
                          Address = o.Address,
                          CNName = Global.IsChinese ? o.CNName : string.IsNullOrEmpty(o.ENName) ? o.CNName : o.ENName,
                          Code = o.Code,
                          Dic_Creatdate = o.Creatdate.Value.ToString(GlobalConst.DATE_FORMAT_MINUTES),
                          Dic_Creator = this.EmpDictionary.ContainsKey(o.Creator.Value) ? this.EmpDictionary[o.Creator.Value] : "",
                          Dic_Enable = o.Status ? this.Resources("dicenable") : this.Resources("dicdisabled"),
                          MenuId = o.MenuId,
                          ParentCode = o.ParentCode,
                          Status = o.Status,
                          RowNo = i,
                          Children = GenerateChildTableMenus(o.Code, menus),
                          id = o.MenuId
                      });
                  i++;
              });
            return _OuPuts.Succeed();
        }

        /// <summary>
        /// 获取树形结构的菜单
        /// </summary>
        /// <returns></returns>
        public IResponseMessage Tree()
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            List<Model.Menus> menus = business.GetMenus();
            List<OutPut.TreeInfo_OutPut> _OuPuts = new List<OutPut.TreeInfo_OutPut>();
            menus.Where(o => string.IsNullOrEmpty(o.ParentCode)).ToList().ForEach(o =>
            {
                _OuPuts.Add(
                    new OutPut.TreeInfo_OutPut()
                    {
                        Icon = o.Icon,
                        Id = o.MenuId,
                        Label = Global.Language == (LanguageType.zh_cn.ToString().Replace("_", "-")) ? o.CNName : string.IsNullOrEmpty(o.ENName) ? o.CNName : o.ENName,
                        Code = o.Code,
                        Children = GenerateChildTreeInfo(o.Code, menus)
                    }); ;
            });
            _OuPuts.Add(new OutPut.TreeInfo_OutPut()
            {
                Label = this.CommonText("commontext"),
                Code = "common"
            });
            _OuPuts.Add(new OutPut.TreeInfo_OutPut()
            {
                Label = this.CommonText("language"),
                Code = "language"
            });
            return _OuPuts.Succeed();
        }

        /// <summary>
        /// 递归获取子菜单
        /// </summary>
        /// <param name="ParentCode"></param>
        /// <param name="menus"></param>
        /// <returns></returns>
        private List<OutPut.MenusInfo_OuPut> GenerateChildMenus(string ParentCode, List<Model.Menus> menus)
        {
            List<OutPut.MenusInfo_OuPut> _OuPuts = null; ;
            List<Model.Menus> childMenus = menus.Where(o => o.Status && o.ParentCode == ParentCode).ToList();
            if (childMenus.Any())
            {
                _OuPuts = new List<OutPut.MenusInfo_OuPut>();
                childMenus.ForEach(o =>
                {
                    if (!_OuPuts.Any(no => no.Code == o.Code))
                        _OuPuts.Add(
                        new OutPut.MenusInfo_OuPut()
                        {
                            Code = o.Code,
                            Icon = o.Icon,
                            Index = string.IsNullOrEmpty(o.Address) ? o.MenuId.ToString() : o.Address,
                            Title = Global.Language == "zh-cn" ? o.CNName : string.IsNullOrEmpty(o.ENName) ? o.CNName : o.ENName,
                            Subs = GenerateChildMenus(o.Code, menus)
                        });
                });
            }
            return _OuPuts;
        }
        /// <summary>
        /// 递归获取子菜单
        /// </summary>
        /// <param name="ParentCode"></param>
        /// <param name="menus"></param>
        /// <returns></returns>
        private List<OutPut.TreeInfo_OutPut> GenerateChildTreeInfo(string ParentCode, List<Model.Menus> menus)
        {
            List<OutPut.TreeInfo_OutPut> _OuPuts = null;
            List<Model.Menus> childMenus = menus.Where(o => o.Status && o.ParentCode == ParentCode).ToList();
            if (childMenus.Any())
            {
                _OuPuts = new List<OutPut.TreeInfo_OutPut>();
                childMenus.ForEach(o =>
                {
                    if (!_OuPuts.Any(no => no.Code == o.Code))
                        _OuPuts.Add(
                        new OutPut.TreeInfo_OutPut()
                        {
                            Icon = o.Icon,
                            Id = o.MenuId,
                            Label = Global.Language == (LanguageType.zh_cn.ToString().Replace("_", "-")) ? o.CNName : string.IsNullOrEmpty(o.ENName) ? o.CNName : o.ENName,
                            Code = o.Code,
                            Children = GenerateChildTreeInfo(o.Code, menus)
                        }); ;
                });
            }
            return _OuPuts;
        }

        /// <summary>
        /// 递归获取子菜单
        /// </summary>
        /// <param name="ParentCode"></param>
        /// <param name="menus"></param>
        /// <returns></returns>
        private List<OutPut.Menus_OuPut> GenerateChildTableMenus(string ParentCode, List<Model.Menus> menus)
        {
            List<OutPut.Menus_OuPut> _OuPuts = null; ;
            List<Model.Menus> childMenus = menus.Where(o => o.ParentCode == ParentCode).OrderBy(o => o.Sequence).ToList();
            if (childMenus.Any())
            {
                _OuPuts = new List<OutPut.Menus_OuPut>();
                int i = 1;
                childMenus.ForEach(o =>
                {
                    if (!_OuPuts.Any(no => no.Code == o.Code))
                        _OuPuts.Add(
                       new OutPut.Menus_OuPut()
                       {
                           Icon = o.Icon,
                           Address = o.Address,
                           CNName = Global.IsChinese ? o.CNName : string.IsNullOrEmpty(o.ENName) ? o.CNName : o.ENName,
                           Code = o.Code,
                           Dic_Creatdate = o.Creatdate.Value.ToString(GlobalConst.DATE_FORMAT_MINUTES),
                           Dic_Creator = EmpDictionary.ContainsKey(o.Creator.Value) ? EmpDictionary[o.Creator.Value] : "",
                           Dic_Enable = o.Status ? this.Resources("dicenable") : this.Resources("dicdisabled"),
                           MenuId = o.MenuId,
                           ParentCode = o.ParentCode,
                           Status = o.Status,
                           RowNo = i,
                           Children = GenerateChildTableMenus(o.Code, menus),
                           id = o.MenuId
                       });
                    i++;
                });
            }
            return _OuPuts;
        }

        private List<OutPut.Menus_OuPut> GenerateNewChildTableMenus(string ParentCode, List<Model.Menus> menus)
        {
            List<OutPut.Menus_OuPut> _OuPuts = null; ;
            List<Model.Menus> childMenus = menus.Where(o => o.ParentCode == ParentCode).OrderBy(o => o.Sequence).ToList();
            if (childMenus.Any())
            {
                _OuPuts = new List<OutPut.Menus_OuPut>();
                int i = 1;
                childMenus.ForEach(o =>
                {
                    if (!_OuPuts.Any(no => no.Code == o.Code))
                    {
                        var outd = new OutPut.Menus_OuPut()
                        {
                            Icon = o.Code,
                            Address = o.Address,
                            CNName = Global.IsChinese ? o.CNName : string.IsNullOrEmpty(o.ENName) ? o.CNName : o.ENName,
                            Code = o.Code,
                            Dic_Creatdate = o.Creatdate.Value.ToString(GlobalConst.DATE_FORMAT_MINUTES),
                            Dic_Creator = this.EmpDictionary.ContainsKey(o.Creator.Value) ? this.EmpDictionary[o.Creator.Value] : "",
                            Dic_Enable = o.Status ? this.Resources("dicenable") : this.Resources("dicdisabled"),
                            MenuId = o.MenuId,
                            ParentCode = o.ParentCode,
                            Status = o.Status,
                            RowNo = i,
                            Children = GenerateNewChildTableMenus(o.Code, menus),
                            id = o.MenuId,
                        };
                        outd.Operations = new List<SystemButton>();
                        if (Global.IsAdmin && (Buttons is null || !Buttons.Any()))
                        {
                            BuliderButtons(outd.Operations, outd.Code, outd.MenuId, ButtomType.add);
                            BuliderButtons(outd.Operations, outd.Code, outd.MenuId, ButtomType.edit);
                            BuliderButtons(outd.Operations, outd.Code, outd.MenuId, ButtomType.role);
                            BuliderButtons(outd.Operations, outd.Code, outd.MenuId, ButtomType.detaile);
                            BuliderButtons(outd.Operations, outd.Code, outd.MenuId, !o.Status ? ButtomType.enable : ButtomType.disable);
                            BuliderButtons(outd.Operations, outd.Code, outd.MenuId, ButtomType.delete);
                        }
                        _OuPuts.Add(outd);
                    }
                    i++;
                });
            }
            return _OuPuts;
        }
        public IResponseMessage Roles(long MenuId)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            TableListModel<ExtMenus_Roles> tableListModel = new TableListModel<ExtMenus_Roles>();
            List<TableListHeaderModele> Headers = new List<TableListHeaderModele>();
            Headers.Add(new TableListHeaderModele() { Key = "menuId", Name = CommonText("autoId"), Hide = true });
            Headers.Add(new TableListHeaderModele() { Key = "roleId", Name = CommonText("autoId"), Hide = true });
            Headers.Add(new TableListHeaderModele() { Key = "roleCode", Name = CommonText("thcode"), Width = 160, Align = "center", SorTable = SortType.custom.ToString() });
            Headers.Add(new TableListHeaderModele() { Key = "roleName", Name = CommonText("btnrole"), Align = "center", SorTable = SortType.custom.ToString() });
            Headers.Add(new TableListHeaderModele() { Key = "action", Name = "操作", Width = 160, Align = "center" });
            List<ExtMenus_Roles> Data = business.Roles(MenuId);
            tableListModel.Body = Data;
            tableListModel.Total = 0;
            tableListModel.Header = Headers;
            if (Global.IsAdmin && (Buttons is null || !Buttons.Any()))
            {
                BuliderButtons(tableListModel.Operations, "", 0, ButtomType.add);
                BuliderButtons(tableListModel.Operations, "", 0, ButtomType.delete);
            }
            else
            {

                if (Buttons.Any(o => o.Value == ButtomType.add.ToString() || o.Value == ButtomType.delete.ToString()))
                {
                    BuliderButtons(tableListModel.Operations, "", 0, ButtomType.add);
                    BuliderButtons(tableListModel.Operations, "", 0, ButtomType.delete);
                }
            }
            return tableListModel.Succeed();
        }

        /// <summary>
        /// 保存角色
        /// </summary>
        /// <param name="_Roles"></param>
        /// <returns></returns>
        public IResponseMessage AddRoles(List<ExtMenus_Roles> _Roles, long menuId)
        {
            List<Model.Menus_Roles> menus_s = new List<Model.Menus_Roles>();
            _Roles.ForEach(item =>
            {
                menus_s.Add(new Model.Menus_Roles() { Creatdate = DateTime.Now, Creator = Global.EmpId, MenuId = menuId, RoleId = item.RoleId, Status = true });
            });
            using (TransactionScope ts = new TransactionScope())
            {
                if (business.AddRoles(menus_s, menuId))
                {
                    ts.Complete();
                    return ErrorType.BUSSINESS_MEEU_ROLES_SUCCESS.OnSucceed(this.Resources(ErrorType.BUSSINESS_MEEU_ROLES_SUCCESS));
                }
                else return ErrorType.BUSSINESS_MENU_ROLES_FAILURE.Failure(this.Resources(ErrorType.BUSSINESS_MENU_ROLES_FAILURE));
            }
        }

        public IResponseMessage Pages(QueryModel queryModel)
        {
            if (!HavePermission) return ErrorType.BUSINESS_WITHOUT_PERMISSION.Failure(this.CommonText(ErrorType.BUSINESS_WITHOUT_PERMISSION));
            TableListModel<Menus_OuPut> tableListModel = new TableListModel<Menus_OuPut>();
            List<TableListHeaderModele> Headers = new List<TableListHeaderModele>();
            Headers.Add(new TableListHeaderModele() { Key = "menuId", Name = CommonText("autoid"), Width = 90, Type = "primary_key", Align = "left", SorTable = SortType.custom.ToString(), Fixed = true, Hide = true });
            Headers.Add(new TableListHeaderModele() { Key = "code", Name = CommonText("thcode"), Width = 160, Align = "left", Fixed = true });
            Headers.Add(new TableListHeaderModele() { Key = "cnName", Name = CommonText("thcnname"), Width = 260, Align = "left", Fixed = true });
            Headers.Add(new TableListHeaderModele() { Key = "icon", Name = "图标", Width = 70, Align = "center", Fixed = true, IsIcon = true });
            Headers.Add(new TableListHeaderModele() { Key = "dic_Enable", Name = CommonText("thstate"), IsTag = true, Width = 100, Align = "center", SorTable = SortType.custom.ToString() });
            Headers.Add(new TableListHeaderModele() { Key = "dic_Creator", Name = CommonText("diccreator"), Width = 120, Align = "center" });
            Headers.Add(new TableListHeaderModele() { Key = "dic_Creatdate", Name = CommonText("diccreatdate"), Width = 160, Align = "center" });
            Headers.Add(new TableListHeaderModele() { Key = "action", Name = "操作", Width = 190, Align = "center" });
            List<Model.Menus> menus = business.All<Model.Menus>();
            List<OutPut.Menus_OuPut> _OuPuts = new List<OutPut.Menus_OuPut>();
            var empDictionary = this.EmpDictionary;
            int i = 1;
            menus.Where(o => string.IsNullOrEmpty(o.ParentCode)).OrderBy(o => o.Sequence).ToList().ForEach(o =>
            {
                var outd = new OutPut.Menus_OuPut()
                {
                    Icon = o.Code,
                    Address = o.Address,
                    CNName = Global.IsChinese ? o.CNName : string.IsNullOrEmpty(o.ENName) ? o.CNName : o.ENName,
                    Code = o.Code,
                    Dic_Creatdate = o.Creatdate.Value.ToString(GlobalConst.DATE_FORMAT_MINUTES),
                    Dic_Creator = this.EmpDictionary.ContainsKey(o.Creator.Value) ? this.EmpDictionary[o.Creator.Value] : "",
                    Dic_Enable = o.Status ? this.Resources("dicenable") : this.Resources("dicdisabled"),
                    MenuId = o.MenuId,
                    ParentCode = o.ParentCode,
                    Status = o.Status,
                    RowNo = i,
                    Children = GenerateNewChildTableMenus(o.Code, menus),
                    id = o.MenuId,
                };
                outd.Operations = new List<SystemButton>();
                if (Global.IsAdmin && (Buttons is null || !Buttons.Any()))
                {
                    BuliderButtons(outd.Operations, outd.Code, outd.MenuId, ButtomType.add);
                    BuliderButtons(outd.Operations, outd.Code, outd.MenuId, ButtomType.edit);
                    BuliderButtons(outd.Operations, outd.Code, outd.MenuId, ButtomType.role);
                    BuliderButtons(outd.Operations, outd.Code, outd.MenuId, ButtomType.detaile);
                    BuliderButtons(outd.Operations, outd.Code, outd.MenuId, !o.Status ? ButtomType.enable : ButtomType.disable);
                    BuliderButtons(outd.Operations, outd.Code, outd.MenuId, ButtomType.delete);
                }
                _OuPuts.Add(outd);
                i++;
            });
            tableListModel.Body = _OuPuts;
            tableListModel.Total = 0;
            tableListModel.Header = Headers;
            if (Global.IsAdmin && (Buttons is null || !Buttons.Any()))
            {
                BuliderButtons(tableListModel.Operations, "", 0, ButtomType.add);
            }
            else
            {
                if (Buttons.Any(o => o.Value == ButtomType.add.ToString()))
                    BuliderButtons(tableListModel.Operations, "", 0, ButtomType.add);
            }
            return tableListModel.Succeed();
        }
    }
}
